const { createServer } = require("http")
const { parse } = require("url")
const next = require("next")
const findFreePort = require("find-free-port");

const dev = process.env.NODE_ENV !== "production"
const app = next({ dev })
const handle = app.getRequestHandler()

// Only enforce lowercase on page routes; static assets must keep case to avoid 404 on case-sensitive FS.
const isStaticRequest = (pathname) => {
    if (!pathname) return false
    if (pathname.startsWith('/_next')) return true
    if (pathname.startsWith('/assets')) return true
    if (pathname.includes('.')) return true
    return false
}

const startServer = (port) => {
    const server = createServer((req, res) => {
        const parsedUrl = parse(req.url, true);
        const { pathname } = parsedUrl;

        // Proxy /svg to backend
        if (pathname && pathname.startsWith('/svg')) {
            const backendPort = process.env.BACKEND_PORT || 8080;
            const options = {
                hostname: 'localhost',
                port: backendPort,
                path: req.url,
                method: req.method,
                headers: req.headers,
            };

            const proxyReq = require('http').request(options, (proxyRes) => {
                res.writeHead(proxyRes.statusCode, proxyRes.headers);
                proxyRes.pipe(res, { end: true });
            });

            proxyReq.on('error', (e) => {
                console.error(`Problem with request: ${e.message}`);
                res.statusCode = 500;
                res.end('Backend unavailable');
            });

            req.pipe(proxyReq, { end: true });
            return;
        }

        // Redirect page routes (non-static) to lowercase; keep static asset casing intact
        if (!isStaticRequest(pathname) && pathname && pathname !== pathname.toLowerCase()) {
            const lowercasePathname = pathname.toLowerCase();
            const queryString = parsedUrl.search || '';
            res.statusCode = 301;
            res.setHeader('Location', `${lowercasePathname}${queryString}`);
            res.end();
            return;
        } else {
            handle(req, res, parsedUrl);
        }
    });

    server.listen(port, () => {
        console.log(`Ready on http://localhost:${port}`);
    }).on('error', (err) => {
        if (err.code === 'EADDRINUSE') {
            console.error(`Port ${port} is already in use.`);
            process.exit(1);
        } else {
            throw err;
        }
    });
};

app.prepare().then(() => {
    if (dev) {
        // In development mode, start server on the first available port starting from 3000
        findFreePort(3000, (err, freePort) => {
            if (err) throw err;
            startServer(freePort);
        });
    } else {
        // In production mode, use the port specified by the PORT environment variable or default to 8080
        const port = parseInt(process.env.PORT, 10) || 8080;
        startServer(port);
    }
});
